package com.zbkj.admin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.pagehelper.PageHelper;
import com.zbkj.admin.model.req.EditEmployeeNoReq;
import com.zbkj.admin.model.req.EditEmployeeReq;
import com.zbkj.admin.model.req.EmployeeListReq;
import com.zbkj.admin.model.vo.EmployeeListVO;
import com.zbkj.admin.service.AdminEmployeeV2Service;
import com.zbkj.admin.service.AdminUserV2Service;
import com.zbkj.dal.base.enums.AccountTypeEnums;
import com.zbkj.dal.base.enums.BooleanEnums;
import com.zbkj.dal.base.enums.EmployeeStatusEnum;
import com.zbkj.dal.base.enums.UserIdentityEnums;
import com.zbkj.dal.base.page.CommonPage;
import com.zbkj.dal.common.exception.CrmebException;
import com.zbkj.dal.common.utils.CrmebDateUtil;
import com.zbkj.dal.dao.*;
import com.zbkj.dal.entity.merchant.Merchant;
import com.zbkj.dal.entity.merchant.MerchantEmployee;
import com.zbkj.dal.entity.user.Employee;
import com.zbkj.dal.entity.user.EmployeeAccount;
import com.zbkj.dal.entity.user.User;
import com.zbkj.service.manager.UserManager;
import com.zbkj.service.model.front.req.user.UpdateUserIdentityReq;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AdminEmployeeV2ServiceImpl implements AdminEmployeeV2Service {

    @Resource
    private UserDao userDao;
    @Resource
    private EmployeeDao employeeDao;

    @Resource
    private MerchantDao merchantDao;

    @Resource
    private UserManager userManager;

    @Resource
    private AdminUserV2Service adminUserV2Service;

    @Resource
    private EmployeeAccountDao employeeAccountDao;

    @Resource
    private MerchantEmployeeDao merchantEmployeeDao;

    @Override
    public CommonPage<EmployeeListVO> employeeList(EmployeeListReq req) {
        LambdaQueryWrapper<Employee> employeeWrapper = new LambdaQueryWrapper<>();
        employeeWrapper.like(Objects.nonNull(req.getName()), Employee::getRealName, req.getName());
        employeeWrapper.eq(Objects.nonNull(req.getMobile()), Employee::getMobile, req.getMobile());
        String employeeNo = null;
        if (Objects.nonNull(req.getUserId())) {
            LambdaQueryWrapper<EmployeeAccount> accountWrapper = new LambdaQueryWrapper<>();
            accountWrapper.eq(EmployeeAccount::getAccountId, req.getUserId());
            accountWrapper.eq(EmployeeAccount::getAccountType, AccountTypeEnums.FRONT.name());
            accountWrapper.eq(EmployeeAccount::getDeleted, BooleanEnums.FALSE.getCode());
            EmployeeAccount employeeAccount = employeeAccountDao.selectOne(accountWrapper);
            if (Objects.isNull(employeeAccount)) {
                return new CommonPage<>();
            }
            employeeNo = employeeAccount.getEmployeeNo();
        }
        Integer merchantId = req.getMerchantId();
        if (Objects.nonNull(req.getMerchantName())) {
            LambdaQueryWrapper<Merchant> merchantWrapper = new LambdaQueryWrapper<>();
            merchantWrapper.like(Merchant::getName, req.getMerchantName());
            merchantWrapper.eq(Merchant::getIsDel, BooleanEnums.FALSE.getCode());
            Merchant merchant = merchantDao.selectOne(merchantWrapper);
            if (Objects.isNull(merchant)) {
                return new CommonPage<>();
            }
            if (Objects.nonNull(req.getMerchantId()) && !Objects.equals(req.getMerchantId(), merchant.getId())) {
                return new CommonPage<>();
            }
        }
        if (Objects.nonNull(merchantId)) {
            LambdaQueryWrapper<MerchantEmployee> merchantWrapper = new LambdaQueryWrapper<>();
            merchantWrapper.eq(MerchantEmployee::getMerchantId, merchantId);
            merchantWrapper.eq(MerchantEmployee::getDeleted, BooleanEnums.FALSE.getCode());
            List<MerchantEmployee> merchantEmployees = merchantEmployeeDao.selectList(merchantWrapper);
            List<String> employeeNos = merchantEmployees.stream().map(MerchantEmployee::getEmployeeNo).collect(Collectors.toList());
            if (Objects.isNull(employeeNo)) {
                employeeWrapper.eq(CollectionUtil.isNotEmpty(employeeNos), Employee::getEmployeeNo, employeeNos);
            } else if (employeeNos.contains(employeeNo)) {
                employeeWrapper.eq(Employee::getEmployeeNo, employeeNo);
            } else {
                return new CommonPage<>();
            }
        } else {
            employeeWrapper.eq(Objects.nonNull(employeeNo), Employee::getEmployeeNo, employeeNo);
        }
        employeeWrapper.eq(Employee::getDeleted, 0);
        PageHelper.startPage(req.getPage(), req.getLimit());
        List<Employee> employees = employeeDao.selectList(employeeWrapper);
        List<String> employeeNos = employees.stream().map(Employee::getEmployeeNo).collect(Collectors.toList());
        LambdaQueryWrapper<MerchantEmployee> merchantEmployeeWrapper = new LambdaQueryWrapper<>();
        merchantEmployeeWrapper.eq(MerchantEmployee::getDeleted, BooleanEnums.FALSE.getCode());
        merchantEmployeeWrapper.eq(MerchantEmployee::getEnable, BooleanEnums.TRUE.getCode());
        merchantEmployeeWrapper.eq(MerchantEmployee::getEmployeeNo, employeeNos);
        List<MerchantEmployee> merchantEmployees = merchantEmployeeDao.selectList(merchantEmployeeWrapper);
        Map<String, MerchantEmployee> merchantEmployeeMap = merchantEmployees.stream().collect(Collectors.toMap(MerchantEmployee::getEmployeeNo, Function.identity(), (a, b) -> a));

        List<Integer> merchantIds = merchantEmployees.stream().map(MerchantEmployee::getMerchantId).collect(Collectors.toList());
        LambdaQueryWrapper<Merchant> merchantWrapper = new LambdaQueryWrapper<>();
        merchantWrapper.in(Merchant::getId, merchantIds);
        List<Merchant> merchants = merchantDao.selectList(merchantWrapper);
        Map<Integer, String> merchantNameMap = merchants.stream().collect(Collectors.toMap(Merchant::getId, Merchant::getName, (a, b) -> a));

        LambdaQueryWrapper<EmployeeAccount> accountWrapper = new LambdaQueryWrapper<>();
        accountWrapper.eq(EmployeeAccount::getAccountType, AccountTypeEnums.FRONT.name());
        accountWrapper.in(EmployeeAccount::getEmployeeNo, employeeNos);
        accountWrapper.eq(EmployeeAccount::getDeleted, BooleanEnums.FALSE.getCode());
        List<EmployeeAccount> employeeAccounts = employeeAccountDao.selectList(accountWrapper);
        Map<String, Integer> accountMap = employeeAccounts.stream().collect(Collectors.toMap(EmployeeAccount::getEmployeeNo, EmployeeAccount::getAccountId, (a, b) -> a));

        List<EmployeeListVO> employeeList = employees.stream().map(employee -> {
            MerchantEmployee merchantEmployee = merchantEmployeeMap.get(employee.getEmployeeNo());
            EmployeeListVO employeeListVO = new EmployeeListVO();
            employeeListVO.setName(employee.getRealName());
            employeeListVO.setEmployeeNo(employee.getEmployeeNo());
            employeeListVO.setMobile(employee.getMobile());
            employeeListVO.setPosition(merchantEmployee.getIdentity());
            employeeListVO.setPositionDesc(UserIdentityEnums.getDescByCode(merchantEmployee.getIdentity()));
            employeeListVO.setMerchantId(merchantEmployee.getMerchantId());
            employeeListVO.setMerchantName(merchantNameMap.get(merchantEmployee.getMerchantId()));
            employeeListVO.setUserId(accountMap.get(employee.getEmployeeNo()));
            employeeListVO.setWechatNickname(employee.getUserName());
            employeeListVO.setStatus(employee.getStatus());
            employeeListVO.setStatus(EmployeeStatusEnum.getDescByCode(employee.getStatus()));
            return employeeListVO;
        }).collect(Collectors.toList());
        CommonPage<Employee> employeeCommonPage = CommonPage.restPage(employees);
        CommonPage<EmployeeListVO> commonPage = new CommonPage<>();
        commonPage.setPage(employeeCommonPage.getPage());
        commonPage.setLimit(employeeCommonPage.getLimit());
        commonPage.setTotalPage(employeeCommonPage.getTotalPage());
        commonPage.setTotal(employeeCommonPage.getTotal());
        commonPage.setList(employeeList);
        return commonPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editEmployee(EditEmployeeReq req) {
        Employee employee = queryEmployee(req.getEmployeeNo());
        if (Objects.isNull(employee)) {
            throw new CrmebException("为查询到员工信息");
        }

        if (Objects.nonNull(req.getUserId())) {

            User user = userManager.findByUserId(req.getUserId());
            if (Objects.isNull(user)) {
                throw new CrmebException("用户信息不存在");
            }
            if (StringUtils.isNotBlank(req.getRealName())) {
                LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(User::getRealName, req.getRealName());
                updateWrapper.set(User::getUpdateTime, CrmebDateUtil.nowDateTime());
                updateWrapper.eq(User::getId, req.getUserId());
                userDao.update(null, updateWrapper);
            }

            LambdaQueryWrapper<EmployeeAccount> employeeAccountWrapper = new LambdaQueryWrapper<EmployeeAccount>()
                    .eq(EmployeeAccount::getEmployeeNo, req.getEmployeeNo())
                    .eq(EmployeeAccount::getAccountType, AccountTypeEnums.FRONT.name())
                    .eq(EmployeeAccount::getDeleted, BooleanEnums.FALSE.getCode());
            EmployeeAccount employeeAccount = employeeAccountDao.selectOne(employeeAccountWrapper);
            if (Objects.isNull(employeeAccount)) {
                EmployeeAccount account = new EmployeeAccount();
                account.setEmployeeNo(req.getEmployeeNo());
                account.setAccountType(AccountTypeEnums.FRONT.name());
                account.setAccountId(req.getUserId());
                account.setAccountNo(user.getAccount());
                account.setCreateTime(LocalDateTime.now());
                account.setUpdateTime(LocalDateTime.now());
                account.setDeleted(BooleanEnums.FALSE.getCode());
                employeeAccountDao.insert(account);
            } else {
                LambdaUpdateWrapper<EmployeeAccount> accountLambdaUpdateWrapper = new LambdaUpdateWrapper<EmployeeAccount>()
                        .set(EmployeeAccount::getAccountId, req.getUserId())
                        .eq(EmployeeAccount::getId, employeeAccount.getId())
                        .eq(EmployeeAccount::getEmployeeNo, req.getEmployeeNo())
                        .eq(EmployeeAccount::getAccountType, AccountTypeEnums.FRONT.name())
                        .eq(EmployeeAccount::getDeleted, BooleanEnums.FALSE.getCode());
                employeeAccountDao.update(null, accountLambdaUpdateWrapper);
            }
        }

        if (Objects.nonNull(req.getMerchantId()) || Objects.nonNull(req.getIdentity()) || Objects.nonNull(req.getUserId())) {
            if (Objects.isNull(req.getMerchantId()) || Objects.isNull(req.getIdentity()) || Objects.isNull(req.getUserId())) {
                throw new CrmebException("修改员工职位时，店铺信息/身份信息/小程序用户id不能为空");
            }
            Merchant merchant = merchantDao.selectById(req.getMerchantId());
            if (Objects.isNull(merchant)) {
                throw new CrmebException("所选店铺信息异常");
            }

            UpdateUserIdentityReq updateReq = new UpdateUserIdentityReq();
            updateReq.setUserId(req.getUserId());
            updateReq.setIdentity(req.getIdentity());
            adminUserV2Service.updateIdentity(req.getEmployeeNo(), req.getUserId(), req.getIdentity(), req.getMerchantId());
        }


        LambdaUpdateWrapper<Employee> employeeLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        employeeLambdaUpdateWrapper.set(Objects.nonNull(req.getRealName()), Employee::getRealName, req.getRealName())
                .set(Objects.nonNull(req.getMobile()), Employee::getMobile, req.getMobile())
                .set(Objects.nonNull(req.getStatus()), Employee::getStatus, req.getStatus())
                .set(Employee::getUpdateTime, LocalDateTime.now())
                .eq(Employee::getEmployeeNo, req.getEmployeeNo())
                .eq(Employee::getDeleted, 0)
                .eq(Employee::getId, employee.getId());
        employeeDao.update(null, employeeLambdaUpdateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editEmployeeNo(EditEmployeeNoReq req) {
        queryEmployee(req.getEmployeeNo());

        employeeDao.updateEmployeeNo(req.getEmployeeNo(), req.getNewEmployeeNo());

        employeeAccountDao.updateEmployeeNo(req.getEmployeeNo(), req.getNewEmployeeNo());

        merchantEmployeeDao.updateEmployeeNo(req.getEmployeeNo(), req.getNewEmployeeNo());

    }

    private Employee queryEmployee(String employeeNo) {
        LambdaQueryWrapper<Employee> employeeWrapper = new LambdaQueryWrapper<Employee>()
                .eq(Employee::getEmployeeNo, employeeNo)
                .eq(Employee::getDeleted, BooleanEnums.FALSE.getCode());
        Employee employee = employeeDao.selectOne(employeeWrapper);
        if (Objects.isNull(employee)) {
            throw new CrmebException("未查询到对应的员工");
        }
        return employee;
    }
}
